package com.sky.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 套餐管理业务逻辑层
 *
 * @Author mr.zhang
 * Date 2025/5/21 15:59
 */
@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;
    @Autowired
    private DishMapper dishMapper;

    public static final String REDIS_SETMEAL_CACHE_KEY_PREFIX = "redis:setmeal:";

    /**
     * 新增套餐
     *
     * @param setmealDTO
     */
    @Override
    public void add(SetmealDTO setmealDTO) {
        // 新增 setmeal 表中数据
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO,setmeal);


        setmealMapper.insert(setmeal);

        // 新增 setmealDishes 表中数据
        Long id = setmealDTO.getId();
        List<SetmealDish> setmealDishList = setmealDTO.getSetmealDishes();
        setmealDishList.forEach(x -> {
            x.setSetmealId(id);
        });
        setmealDishMapper.batchAdd(setmealDishList);



        //清除缓存
        redisTemplate.delete(REDIS_SETMEAL_CACHE_KEY_PREFIX);
    }




    /**
     * 分页条件查询
     *
     * @param dto
     * @return
     */
    @Override
    public PageResult listPage(SetmealPageQueryDTO dto) {
        //设置分页参数
        PageHelper.startPage(dto.getPage(),dto.getPageSize());
        //调用mapper层方法
        List<SetmealVO> setmealVOList = setmealMapper.listPage(dto);
        //使用Page强转
        Page<SetmealVO> page = (Page<SetmealVO>) setmealVOList;
        //返回数据
        return new PageResult(page.getTotal(),page.getResult());
    }

    /**
     * 删除套餐
     *
     * @param ids
     */
    @Override
    public void delete(List<Integer> ids) throws Exception {
        //根据ids查询套餐中是否有起售状态,有的话显示无法删除
        int count = setmealMapper.getCountByStatus(ids);
        if(count>0){
            throw new Exception("套餐正在起售中,无法删除");
        }
        //删除套餐
        setmealMapper.delete(ids);
        //删除套餐下的菜品

        setmealDishMapper.delete(ids);


        //清除缓存
        redisTemplate.delete(REDIS_SETMEAL_CACHE_KEY_PREFIX);

    }


    /**
     * 查询回显,根据id查询套餐数据
     *
     * @param id
     * @return
     */
    @Override
    public SetmealVO getById(Long id) throws Exception {
        //创建值对象实例,实体类实例
        SetmealVO setmealVO = new SetmealVO();
        Setmeal setmeal = new Setmeal();

        //调用setmealMapper层方法获取setmeal数据
        setmeal = setmealMapper.getById(id);
        if(setmeal==null){
            throw new Exception("对应id的套餐不存在");
        }
        BeanUtils.copyProperties(setmeal,setmealVO);
        setmealVO.setUpdateTime(LocalDateTime.now());

        //调用setmealDishMapper方法获取setmeal_dish数据
        List<SetmealDish> setmealDishList = setmealDishMapper.getBySetmealId(id);
        setmealVO.setSetmealDishes(setmealDishList);

        return setmealVO;
    }

    /**
     * 修改套餐
     *
     * @param dto
     */
    @Override
    public void update(SetmealDTO dto) {
        //1.修改套餐
        //创建实体类实例
        Setmeal setmeal = new Setmeal();
        //拷贝
        BeanUtils.copyProperties(dto,setmeal);
        setmealMapper.update(setmeal);


        List<SetmealDish> setmealDishList = dto.getSetmealDishes();
        //2.删除套餐菜品关联表中的数据
        //将integer类型id转为集合List,由于获取的数据是Long类型,转为integer
        setmealDishMapper.delete(ListUtil.toList(Math.toIntExact(dto.getId())));

        //3.重新新增套餐菜品关联表中数据
        setmealDishMapper.batchAdd(setmealDishList);

        //清除缓存
        redisTemplate.delete(REDIS_SETMEAL_CACHE_KEY_PREFIX);
    }


    /**
     * 修改套餐起售与停售状态
     *
     * @param status
     * @param id
     */
    @Override
    public void updateStatus(Integer status, Long id) throws Exception {
        Setmeal setmeal1 = setmealMapper.getById(id);

        Setmeal setmeal = new Setmeal();
        setmeal.setStatus(status);
        setmeal.setId(id);

        if (setmeal1==null){
            throw new Exception("此id无对应套餐数据");
        }

        //判断起售时套餐中的菜品是否有停售的,有的话,返回套餐中有停售菜品,禁止删除
        //根据套餐id查询其中的菜品
        List<SetmealDish> dishList = setmealDishMapper.getBySetmealId(id);
        //首先判断套餐是什么状态,如果是起售状态,想改变直接进行;停售状态,想改变,先判断
        if(setmeal1.getStatus()==0){
            //遍历dishList,判断起售与停售状态,如果有停售,立刻结束便利,返回错误
            for (SetmealDish setmealDish : dishList) {
                Long dishId = setmealDish.getDishId();
                if(dishMapper.getById( Math.toIntExact(dishId)).getStatus()==0){
                    throw new Exception("套餐中的菜品有停售状态,不能起售");
                }
            }
        }
        setmealMapper.update(setmeal);

        //清除缓存
        redisTemplate.delete(REDIS_SETMEAL_CACHE_KEY_PREFIX);
    }

    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 根据分类id查询
     * @param setmeal
     * @return
     */
    public List<Setmeal> list(Setmeal setmeal) {

        // 强制设置为启用状态
        setmeal.setStatus(StatusConstant.ENABLE);

        String key = REDIS_SETMEAL_CACHE_KEY_PREFIX + setmeal.getCategoryId();

        // 1. 先从 Redis List 中读取缓存
        List<String> cachedJsonList = redisTemplate.opsForList().range(key, 0, -1);
        if (CollUtil.isNotEmpty(cachedJsonList)) {
            // 将 JSON 字符串反序列化为 Setmeal 对象列表
            List<Setmeal> setmealList = new ArrayList<>();
            for (String json : cachedJsonList) {
                List<Setmeal> setmeals = JSON.parseArray(json, Setmeal.class);
                setmealList.addAll(setmeals);
            }
            return setmealList;
        }

        // 2. 缓存未命中，查询数据库
        List<Setmeal> setmealList = setmealMapper.list(setmeal);
        if (CollUtil.isEmpty(setmealList)) {
            return ListUtil.empty();
        }

        // 3. 将数据写入 Redis List 缓存
        // 3. 写入缓存：将每个对象转为 JSON 字符串后插入到 Redis List 中
        redisTemplate.opsForList().leftPush(key,JSON.toJSONString(setmealList));
        return setmealList;
    }


    /**
     * 根据id查询菜品选项
     * @param id
     * @return
     */
    public List<DishItemVO> getDishItemById(Long id) {
        return setmealMapper.getDishItemBySetmealId(id);
    }
}
